package net.keebook.webapp.dao;

import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.Query;

import net.keebook.webapp.entity.KeeBook;
import net.keebook.webapp.entity.KeeBookAccess;
import net.keebook.webapp.entity.User;
import net.keebook.webapp.model.SessionModel;
import net.keebook.webapp.util.AccessRight;


@Stateless
public class KeeBookDao extends Dao<KeeBook> {
	@Override
	public void store(KeeBook item) {
		super.store(item);
	}
	
	@Override
	public void update(KeeBook item) {
		super.update(item);
	}
	
	@Override
	public KeeBook get(Long id) {
		return super.get(id);
	}
	
	@Override
	public KeeBook get(String id) {
		return super.get(id);
	}
	
	@Override
	public void delete(KeeBook item) {
		getEntityManager().createQuery("DELETE FROM KeeBookAccess a WHERE a.pk.keeBook.id = :keeBookId").setParameter("keeBookId", item.getId()).executeUpdate();
		getEntityManager().createQuery("DELETE FROM PasswordItem p WHERE p.keeBook.id = :keeBookId").setParameter("keeBookId", item.getId()).executeUpdate();
		getEntityManager().createQuery("DELETE FROM ItemGroup g WHERE g.keeBook.id = :keeBookId").setParameter("keeBookId", item.getId()).executeUpdate();
		getEntityManager().createQuery("DELETE FROM ShareRequest s WHERE s.keeBook.id = :keeBookId").setParameter("keeBookId", item.getId()).executeUpdate();
		super.delete(item);
	}
	
	@SuppressWarnings("unchecked")
	public List<KeeBook> getList(Long userId) {
		Query query = getEntityManager().createQuery("SELECT a.pk.keeBook FROM KeeBookAccess a WHERE a.pk.user.id = :userId ORDER BY a.pk.keeBook.name");
		query.setParameter("userId", userId);
		return detachAll(query.getResultList());
	}
	
	@SuppressWarnings("unchecked")
	public List<KeeBookAccess> getAccessListForKeeBook(Long keeBookId) {
		Query query = getEntityManager().createQuery("FROM KeeBookAccess a WHERE a.pk.keeBook.id = :keeBookId ORDER BY a.pk.user.username");
		query.setParameter("keeBookId", keeBookId);
		List<KeeBookAccess> accessList = (List<KeeBookAccess>)query.getResultList();
		return accessList;
	}
	
	@SuppressWarnings("unchecked")
	public List<KeeBookAccess> getAccessListForUser(Long userId) {
		Query query = getEntityManager().createQuery("FROM KeeBookAccess a WHERE a.pk.user.id = :userId");
		query.setParameter("userId", userId);
		List<KeeBookAccess> accessList = (List<KeeBookAccess>)query.getResultList();
		return accessList;
	}
	
	public KeeBookAccess getAccessRight(String id) {
		Query query = getEntityManager().createQuery("FROM KeeBookAccess a WHERE a.exposableId = :id");
		query.setParameter("id", id);
		query.setMaxResults(1);
		@SuppressWarnings("unchecked")
		List<KeeBookAccess> result = (List<KeeBookAccess>)query.getResultList();
		if (result.isEmpty()) {
			return null;
		}
		KeeBookAccess access = result.get(0);
		getEntityManager().detach(access);
		return access;
	}
	
	public KeeBookAccess getAccessRight(Long userId, Long keeBookId) {
		Query query = getEntityManager().createQuery("FROM KeeBookAccess a WHERE a.pk.user.id = :userId AND a.pk.keeBook.id = :keeBookId");
		query.setParameter("userId", userId);
		query.setParameter("keeBookId", keeBookId);
		query.setMaxResults(1);
		@SuppressWarnings("unchecked")
		List<KeeBookAccess> result = (List<KeeBookAccess>)query.getResultList();
		if (result.isEmpty()) {
			return null;
		}
		KeeBookAccess access = result.get(0);
		getEntityManager().detach(access);
		return access;
	}
	
	public AccessRight getKeeBookAccess(SessionModel sessionModel) {
		if (!sessionModel.getKeeBookSelected()) {
			return null;
		}
		KeeBookAccess access = getAccessRight(sessionModel.getUserId(), sessionModel.getKeeBookId());
		if (access == null) {
			return null;
		}
		return access.getAccessRight();
	}
	
	public Boolean getKeeBookAccess(SessionModel sessionModel, AccessRight requiredRight) {
		AccessRight accessRight = getKeeBookAccess(sessionModel);
		if (accessRight == null) {
			return false;
		}
		return (accessRight.compareTo(requiredRight) >= 0);
	}
	
	public Boolean getKeeBookAccess(SessionModel sessionModel, String requiredLevel) {
		AccessRight requiredRight = AccessRight.valueOf(requiredLevel);
		return getKeeBookAccess(sessionModel, requiredRight);
	}
	
	public boolean canAccess(Long userId, Long keeBookId) {
		return getAccessRight(userId, keeBookId) != null;
	}
	
	public boolean canAccess(Long userId, Long keeBookId, AccessRight requiredRight) {
		KeeBookAccess kba = getAccessRight(userId, keeBookId);
		if (kba == null) return false;
		AccessRight accessRight = kba.getAccessRight();
		return (accessRight.compareTo(requiredRight) >= 0);
	}
	
	public void removeAccessRight(Long userId, Long keeBookId) {
		KeeBookAccess access = getAccessRight(userId, keeBookId);
		if (access != null) {
			getEntityManager().remove(getEntityManager().merge(access));
		}
	}
	
	public void removeAccessRight(String exposableId) {
		getEntityManager().createQuery("DELETE FROM KeeBookAccess a WHERE a.exposableId = :exposableId").setParameter("exposableId", exposableId).executeUpdate();
	}
	
	public void setAccessRight(User user, KeeBook keeBook, AccessRight right) {
		KeeBookAccess access = new KeeBookAccess();
		access.setExposableId(generateExposableId(KeeBookAccess.class.getSimpleName()));
		access.setUser(user);
		access.setKeeBook(keeBook);
		access.setAccessRight(right);
		access = getEntityManager().merge(access);
	}
}
